home *** CD-ROM | disk | FTP | other *** search
- /*
-
- File: hdaccess.c
-
- Copyright (C) 1998-2001 Christophe Grenier <grenier@nef.esiea.fr>
-
- This software is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
- #define LINUX_WRITE 1
- #ifdef LINUX_WRITE
- #define open_mode O_RDWR
- #else
- #define open_mode O_RDONLY
- #endif
- #ifdef DJGPP
- #include <stdlib.h> /* atexit */
- #include <stdio.h>
- #include <go32.h> /* dosmemget/put */
- #include <dpmi.h>
- #include <bios.h> /* bios_k* */
- #include "types.h"
- #include "common.h"
- #include "fnctdsk.h"
- #include "hdaccess.h"
- //#include "interface.h"
- #define HD_RW_BUF_SIZ 0x10
- #define HDPARM_BUF_SIZ 0x1A
- #define MAX_IO_NBR 10
- #define PARA_CMD 8
- int hd_super(int, t_param_disk_cst, int, int, int, int, void*);
- int hd_identify_bios(t_param_disk param_disk);
- int hd_identify_enh_bios(t_param_disk param_disk);
- int check_enh_bios(t_param_disk param_disk, const int debug);
- static int dos_segment = 0;
- static int dos_selector = 0;
-
- void free_dos_buffer(void)
- {
- __dpmi_free_dos_memory(dos_selector);
- dos_segment = dos_selector = 0;
- }
-
- int alloc_dos_buffer(void)
- {
- if (dos_segment)
- return 0;
- if ((dos_segment = __dpmi_allocate_dos_memory(18*512/16, &dos_selector))== -1)
- {
- dos_segment = 0;
- return 1;
- }
- atexit(free_dos_buffer);
- return 0;
- }
-
- int hd_super(int cmd, t_param_disk_cst disk_car, int head, int track, int sector, int nsects, void *buffer)
- {
- __dpmi_regs r;
- uchar buf[HD_RW_BUF_SIZ];
- int dos_segment2, dos_selector2, xfer2=nsects*512;
- #ifdef DEBUG
- printf("hd_super cmd=%d track=%d head=%d sector=%d\n",cmd,track,head,sector);
- #endif
- if(disk_car->mode==0)
- { // Limite CHS= 1023,255,63 = 8,064Mo ~= 7.8 Go
- if(track<1024)
- return biosdisk(cmd, disk_car->disk, head, track, sector, nsects, buffer);
- return 1;
- }
- if(dos_segment==0)
- if(alloc_dos_buffer())
- return 1;
- if ( (dos_segment2=__dpmi_allocate_dos_memory((xfer2 + 15) >> 4, &dos_selector2)) == -1 )
- return 1;
- *(word*)&buf[0]=HD_RW_BUF_SIZ;
- *(word*)&buf[2]=nsects;
- *(dword*)&buf[0x4]=dos_segment2<<16;
- *(dword*)&buf[0x8]=(track*(disk_car->CHS.head+1)+head)* disk_car->CHS.sector+sector-1;
- *(dword*)&buf[0xC]=0;
-
- r.x.ds = dos_segment;
- r.x.si = 0;
- r.h.dl = disk_car->disk;
- switch(cmd)
- {
- case 2:
- r.h.ah = 0x42;
- break;
- case 3:
- r.x.ax = 0x4300;
- dosmemput(buffer,xfer2,dos_segment2<<4);
- break;
- case 0x0C:
- r.h.ah = 0x47;
- break;
- }
- dosmemput(&buf, HD_RW_BUF_SIZ, dos_segment<<4);
- __dpmi_int(0x13, &r);
- if(cmd==2)
- dosmemget(dos_segment2<<4, xfer2, buffer);
- __dpmi_free_dos_memory(dos_selector2);
- #ifdef DEBUG
- if(r.h.ah)
- {
- doprintf(" %ld err %02X %04X\n",*(dword*)&buf[0x8], r.h.ah,r.x.flags);
- }
- #endif
- return r.h.ah;
- }
-
- int check_enh_bios(t_param_disk param_disk, const int debug)
- {
- __dpmi_regs r;
- r.h.ah = 0x41;
- r.x.bx = 0x55AA;
- r.h.dl = param_disk->disk;
- __dpmi_int(0x13, &r);
- if(r.x.bx != 0xAA55) /* INT 13 Extensions not installed */
- return 0;
- if(debug)
- {
- printf("Disk %02X\n",param_disk->disk);
- switch(r.h.ah)
- {
- case 0x01:
- printf("Enhanced BIOS 1.x\n");
- break;
- case 0x20:
- printf("Enhanced BIOS 2.0 / EDD-1.0\n");
- break;
- case 0x21:
- printf("Enhanced BIOS 2.1 / EDD-1.1\n");
- break;
- case 0x30:
- printf("Enhanced BIOS EDD-3.0\n");
- break;
- default:
- printf("Enhanced BIOS unknow %02X\n",r.h.ah);
- break;
- }
- if((r.x.cx & 1)!=0)
- printf("Extended disk access functions R/W/I Ok\n");
- if((r.x.cx & 4)!=0)
- printf("Enhanced disk drive (EDD) functions identify Ok\n");
- }
- return ((r.x.cx&1)!=0);
- }
-
- int hd_identify_enh_bios(t_param_disk param_disk)
- {
- __dpmi_regs r;
- uchar buf[HDPARM_BUF_SIZ];
- buf[0]=HDPARM_BUF_SIZ;
- buf[1]=0;
- if(dos_segment==0)
- if(alloc_dos_buffer())
- return 1;
- r.h.ah = 0x48;
- r.x.ds = dos_segment;
- r.x.si = 0;
- r.h.dl = param_disk->disk;
- dosmemput(&buf, HDPARM_BUF_SIZ, dos_segment<<4);
- __dpmi_int(0x13, &r);
- dosmemget(dos_segment<<4, HDPARM_BUF_SIZ, &buf);
- if(r.h.ah)
- return 1;
- param_disk->CHS.cylinder=*(word*)&buf[0x04];
- param_disk->CHS.head=*(word*)&buf[0x08];
- param_disk->CHS.sector=*(word*)&buf[0x0C];
- if(param_disk->CHS.cylinder)
- {
- param_disk->CHS.cylinder--;
- param_disk->CHS.head--;
- }
- else
- { /* ATTENTION qword en fait */
- param_disk->CHS.cylinder=(*(dword*)&buf[0x10]/255)/63-1;
- param_disk->CHS.head=255-1;
- param_disk->CHS.sector=63;
- }
- #ifdef DEBUG
- printf("hd_identify_enh_bios\n");
- #endif
- // aff_disk_rapport(param_disk);
- return 0;
- }
-
- int hd_identify_bios(t_param_disk param_disk)
- {
- uchar buf[0x200];
- if(biosdisk(PARA_CMD,param_disk->disk,0,0,1,1,buf))
- return 1;
- param_disk->CHS.cylinder=((buf[0] & 0x0C0)<<2)|buf[1];
- param_disk->CHS.head=buf[3];
- param_disk->CHS.sector=buf[0] & 0x3F;
- #ifdef DEBUG
- printf("hd_identify_bios\n");
- #endif
- // aff_disk_rapport(param_disk);
- return 0;
- }
-
- int hd_identify(t_param_disk param_disk, const int debug)
- {
- int err=1;
- param_disk->mode=check_enh_bios(param_disk,debug);
- if(!hd_identify_bios(param_disk))
- {
- err=0;
- if(!biosdisk(0x0C, param_disk->disk, param_disk->CHS.head, param_disk->CHS.cylinder+1, param_disk->CHS.sector, 0, NULL))
- {
- param_disk->CHS.cylinder++;
- if(debug)
- printf("BIOS hides the last sector.\n");
- }
- }
- if(param_disk->mode)
- return hd_identify_enh_bios(param_disk);
- return err;
- }
-
- int hd_read(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
- {
- int i,rc=-1;
- for(i=0;(rc!=0) && (i<MAX_IO_NBR);i++)
- rc=hd_super(2, disk_car, lieu->head, lieu->cylinder, lieu->sector, nbr_secteur, nom_buffer);
- /*
- for(i=0;i<0x10;i++)
- printf("%02X ",*(char*)(nom_buffer+i));
- printf("\n");
- fflush(stdout);
- */
- return rc;
- }
-
- int hd_read2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
- {
- int i,rc=-1;
- for(i=0;(rc!=0) && (i<MAX_IO_NBR);i++)
- rc=hd_super(2, disk_car, lieu->start.head, lieu->start.cylinder, lieu->start.sector, nbr_secteur, nom_buffer);
- #ifdef DEBUG
- for(i=0;i<0x10;i++)
- printf("%02X ",*(char*)(nom_buffer+i));
- printf("\n");
- fflush(stdout);
- #endif
- return rc;
- }
-
- int hd_write(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
- {
- int i,rc=-1;
- for(i=0;(rc!=0)&&(i<MAX_IO_NBR);i++)
- rc=hd_super(3, disk_car, lieu->head, lieu->cylinder, lieu->sector, nbr_secteur, nom_buffer);
- return rc;
- }
-
- int hd_write2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
- {
- int i,rc=-1;
- for(i=0;(rc!=0)&&(i<MAX_IO_NBR);i++)
- rc=hd_super(3, disk_car, lieu->start.head, lieu->start.cylinder, lieu->start.sector, nbr_secteur, nom_buffer);
- return rc;
- }
-
- int hd_parse(t_param_disk param_disk[NBR_DISK_MAX],const int debug)
- {
- int i;
- int nbr_disk=0;
- for(i=0x80;i<0x88;i++)
- {
- param_disk[nbr_disk]->disk=i;
- if(!hd_identify(param_disk[nbr_disk],debug))
- nbr_disk++;
- }
- return nbr_disk;
- }
- #elif defined(LINUX)
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <linux/hdreg.h>
- #include <fcntl.h>
- #include <sys/mount.h>
- #include <string.h>
- #include "types.h"
- #include "common.h"
- #include "fnctdsk.h"
- #include "hdaccess.h"
-
- loff_t llseek(int,loff_t, int);
- /* if llseek don't work well, try lseek64 */
-
- int hd_read(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
- {
- int i;
- loff_t pos;
- pos=((loff_t) get_LBA(disk_car,lieu))<<9;
- i=llseek(lieu->disk,pos,SEEK_SET);
- if(i==-1)
- return -1;
- if(read(lieu->disk, nom_buffer, nbr_secteur*0x200)==-1)
- return -1;
- return 0;
- }
-
- int hd_write(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
- {
- #ifdef LINUX_WRITE
- int i;
- loff_t pos;
- pos=((loff_t) get_LBA(disk_car,lieu))<<9;
- i=llseek(lieu->disk,pos,SEEK_SET);
- if(i==-1)
- return -1;
- if(write(lieu->disk, nom_buffer, nbr_secteur*0x200)<0)
- return -1;
- return 0;
- #else
- return 1;
- #endif
- }
-
- int hd_read2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
- {
- int i;
- loff_t pos;
- pos=((loff_t) get_LBA_part(disk_car,lieu))<<9;
- i=llseek(lieu->disk,pos,SEEK_SET);
- if(i==-1)
- return -1;
- read(lieu->disk, nom_buffer, nbr_secteur*0x200);
- return 0;
- }
-
- int hd_write2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
- {
- #ifdef LINUX_WRITE
- int i;
- loff_t pos;
- pos=((loff_t) get_LBA_part(disk_car,lieu))<<9;
- i=llseek(lieu->disk,pos,SEEK_SET);
- if(i==-1)
- return -1;
- if(write(lieu->disk, nom_buffer, nbr_secteur*0x200)<0)
- return -1;
- return 0;
- #else
- return 1;
- #endif
- }
-
- void test_disk_availability(int * nbr_disk,t_param_disk param_disk[NBR_DISK_MAX], char *device);
- void test_disk_availability(int * nbr_disk,t_param_disk param_disk[NBR_DISK_MAX], char *device)
- {
- struct hd_geometry geometry;
- int hd_h = open(device, open_mode);
- if(hd_h>0)
- {
- /* Little trick from Linux fdisk */
- /* Blocks are visible in more than one way:
- e.g. as block on /dev/hda and as block on /dev/hda3
- By a bug in the Linux buffer cache, we will see the old
- contents of /dev/hda when the change was made to /dev/hda3.
- In order to avoid this, discard all blocks on /dev/hda. */
- ioctl(hd_h, BLKFLSBUF); /* ignore errors */
- /* e.g. Permission Denied */
- if (!ioctl(hd_h, HDIO_GETGEO, &geometry))
- { /* I can get the geometry */
- param_disk[*nbr_disk]->name=MALLOC(strlen(device)+1);
- strcpy(param_disk[*nbr_disk]->name,device);
- param_disk[*nbr_disk]->CHS.cylinder= geometry.cylinders-1;
- param_disk[*nbr_disk]->CHS.head=geometry.heads-1;
- param_disk[*nbr_disk]->CHS.sector= geometry.sectors;
- param_disk[*nbr_disk]->disk= hd_h;
- (*nbr_disk)++;
- }
- else
- close(hd_h);
- }
- }
-
- int hd_parse(t_param_disk param_disk[NBR_DISK_MAX],const int debug)
- {
- int i;
- char device_ide[]="/dev/hda";
- char device_scsi[]="/dev/sda";
- char device_ida[]="/dev/ida/c0d0";
- int nbr_disk=0;
- /* Disk IDE */
- for(i=0;i<8;i++)
- {
- device_ide[strlen(device_ide)-1]='a'+i;
- test_disk_availability(&nbr_disk,param_disk, device_ide);
- }
- /* Disk SCSI */
- for(i=0;i<8;i++)
- {
- device_scsi[strlen(device_scsi)-1]='a'+i;
- test_disk_availability(&nbr_disk,param_disk, device_scsi);
- }
- /* Device RAID Compaq */
- test_disk_availability(&nbr_disk,param_disk, device_ida);
- return nbr_disk;
- }
- #else
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <fcntl.h>
- #include <sys/disklabel.h>
- #include "types.h"
- #include "common.h"
- #include "fnctdsk.h"
- #include "hdaccess.h"
-
- int hd_read(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
- {
- int i;
- off_t pos;
- pos=((off_t) get_LBA(disk_car,lieu))<<9;
- printf("hd_read at %ld\n", pos);
- i=lseek(lieu->disk,pos,SEEK_SET);
- if(i==-1)
- return -1;
- if(read(lieu->disk, nom_buffer, nbr_secteur*0x200)==-1)
- return -1;
- return 0;
- }
-
- int hd_write(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_disk_cst lieu)
- {
- #ifdef LINUX_WRITE
- int i;
- off_t pos;
- pos=((off_t) get_LBA(disk_car,lieu))<<9;
- i=lseek(lieu->disk,pos,SEEK_SET);
- if(i==-1)
- return -1;
- if(write(lieu->disk, nom_buffer, nbr_secteur*0x200)<0)
- return -1;
- return 0;
- #else
- return 1;
- #endif
- }
-
- int hd_read2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
- {
- int i;
- off_t pos;
- pos=((off_t) get_LBA_part(disk_car,lieu))<<9;
- i=lseek(lieu->disk,pos,SEEK_SET);
- if(i==-1)
- return -1;
- read(lieu->disk, nom_buffer, nbr_secteur*0x200);
- return 0;
- }
-
- int hd_write2(t_param_disk_cst disk_car,const uint nbr_secteur, void *nom_buffer, t_diskext_cst lieu)
- {
- #ifdef LINUX_WRITE
- int i;
- off_t pos;
- pos=((off_t) get_LBA_part(disk_car,lieu))<<9;
- i=lseek(lieu->disk,pos,SEEK_SET);
- if(i==-1)
- return -1;
- if(write(lieu->disk, nom_buffer, nbr_secteur*0x200)<0)
- return -1;
- return 0;
- #else
- return 1;
- #endif
- }
-
- void test_disk_availability(int * nbr_disk,t_param_disk param_disk[NBR_DISK_MAX], char *device);
- void test_disk_availability(int * nbr_disk,t_param_disk param_disk[NBR_DISK_MAX], char *device)
- {
- struct disklabel geometry;
- int hd_h = open(device, open_mode);
- if(hd_h>0)
- {
- if (!ioctl(hd_h, DIOCGDINFO, &geometry))
- { /* I can get the geometry */
- param_disk[*nbr_disk]->name=MALLOC(strlen(device)+1);
- strcpy(param_disk[*nbr_disk]->name,device);
- /*
- param_disk[*nbr_disk]->CHS.cylinder= geometry.cylinders-1;
- param_disk[*nbr_disk]->CHS.head=geometry.heads-1;
- param_disk[*nbr_disk]->CHS.sector= geometry.sectors;
- */
- param_disk[*nbr_disk]->CHS.cylinder=geometry.d_ncylinders-1;
- param_disk[*nbr_disk]->CHS.head=geometry.d_ntracks-1;
- param_disk[*nbr_disk]->CHS.sector=geometry.d_nsectors;
- param_disk[*nbr_disk]->disk= hd_h;
- (*nbr_disk)++;
- }
- else
- close(hd_h);
- }
- }
-
- int hd_parse(t_param_disk param_disk[NBR_DISK_MAX],const int debug)
- {
- int i;
- char device_ide[]="/dev/rwd0";
- char device_scsi[]="/dev/rda0";
- char device_optdisk[]="/dev/rod0";
- int nbr_disk=0;
- /* Disk IDE */
- for(i=0;i<8;i++)
- {
- device_ide[strlen(device_ide)-1]='0'+i;
- test_disk_availability(&nbr_disk,param_disk, device_ide);
- }
- /* Disk SCSI */
- for(i=0;i<8;i++)
- {
- device_scsi[strlen(device_scsi)-1]='0'+i;
- test_disk_availability(&nbr_disk,param_disk, device_scsi);
- }
- /* optical disks */
- for(i=0;i<8;i++)
- {
- device_optdisk[strlen(device_scsi)-1]='a'+i;
- test_disk_availability(&nbr_disk,param_disk, device_optdisk);
- }
- return nbr_disk;
- }
- #endif
-